/*******************************************************************************
 * Copyright (c) 2011 - 2012 TXT e-solutions SpA
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * This work was performed within the IoT_at_Work Project
 * and partially funded by the European Commission's
 * 7th Framework Programme under the research area ICT-2009.1.3
 * Internet of Things and enterprise environments.
 *
 *
 * Authors:
 *     Cristoforo Seccia (TXT e-solutions SpA)
 *     Salvatore Piccione (TXT e-solutions SpA)
 *
 * Contributors:
 *      Domenico Rotondi (TXT e-solutions SpA)
 *******************************************************************************/
package it.txt.access.capability.revocation.wizard;

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JOptionPane;

/**
 *
 * @author Cristoforo Seccia (TXT e-solutions SpA)
 * @author Salvatore Piccione (TXT e-solutions SpA - salvatore.piccione AT network.txtgroup.com)
 */
public class WizardController {

    private static final Logger LOGGER = Logger.getLogger(WizardController.class.getName());
    private WizardPanelDescriptor currentPanel;
    private String previousPanelIdentifier;
    private HashMap panelHashmap;
    private Wizard myWizard;

    protected WizardController(Wizard wizard) {
        panelHashmap = new HashMap();
        myWizard = wizard;
        myWizard.addWindowListener(new WindowListener() {
            
            public void windowOpened(WindowEvent e) {
                //do nothing
            }
            
            public void windowIconified(WindowEvent e) {
                //do nothing
            }
            
            public void windowDeiconified(WindowEvent e) {
                //do nothing
            }
            
            public void windowDeactivated(WindowEvent e) {
                //do nothing
            }
            
            public void windowClosing(WindowEvent e) {
                //check if we are in the last panel and we require user confirmation
                if (WizardPanelDescriptor.FINISH_PANEL_ID.equals(
                        getCurrentPanelDescriptor().getNextIdentifier()) && 
                        getCurrentPanelDescriptor().isUserConfirmationRequired()) {
                    Object[] options = {"Yes", "No"};
                    int resp = JOptionPane.showOptionDialog(myWizard,
                            "The Capability Revocation token was not saved. Do you still want to close the wizard? ",
                            "Capability Revocation token not saved",
                            JOptionPane.YES_NO_OPTION,
                            JOptionPane.WARNING_MESSAGE,
                            null,
                            options,
                            options[0]);
                    if (resp == JOptionPane.YES_OPTION) {
                        closeWizardAndExitApplication();
                    }
                } else if (myWizard.getReturnCode() == Wizard.FINISH_RETURN_CODE
                        && !getCurrentPanelDescriptor().isUserConfirmationRequired()) {
                    //the token has been saved and I've cliked on finish
                    closeWizardAndExitApplication();
                }
                else {
                    int result = JOptionPane.showConfirmDialog(myWizard, 
                            "Are you sure you want to close the wizard?", "Confirm dialog",
                            JOptionPane.YES_NO_OPTION);
                    if (result == JOptionPane.YES_OPTION) {
                        closeWizardAndExitApplication();
                    }
                }
            }
            
            public void windowClosed(WindowEvent e) {
                //do nothing
            }
            
            public void windowActivated(WindowEvent e) {
                //do nothing
            }
        });
    }
    
    private void closeWizardAndExitApplication () {
        if (myWizard.isDisplayable()) {
            myWizard.setVisible(false);
            myWizard.dispose();
        }
        switch (myWizard.getReturnCode()) {
        case Wizard.CANCEL_RETURN_CODE: {
            LOGGER.log(Level.WARNING, "Wizard return code is 'Cancel'.");
            break;
        }
        case Wizard.ERROR: {
            LOGGER.log(Level.SEVERE, "Wizard return code is 'Error'.");
            break;
        }
        case Wizard.FINISH_RETURN_CODE: {
            LOGGER.log(Level.INFO, "Wizard return code is 'Finish'.");
            break;
        }
    }
        System.exit(0);
    }

    protected WizardPanelDescriptor getCurrentPanelDescriptor() {
        return currentPanel;
    }

    protected void registerPanel(String id, WizardPanelDescriptor descriptor) {
        panelHashmap.put(id, descriptor);
        descriptor.getPanelController();
    }

    protected boolean registerCurrentPanel(String id) throws WizardException {
        WizardPanelDescriptor nextPanel =
                (WizardPanelDescriptor) panelHashmap.get(id);
        if (nextPanel == null) {
            throw new WizardException("Wizard Panel not found.");
        }
        currentPanel = nextPanel;
        return true;
    }

    protected void setCurrentPanel(String id, String occurredAction) {
        if (occurredAction.equals(Wizard.START_ACTION)) {
            setStartingPanel(id);
        } else if (occurredAction.equals(Wizard.BACK_ACTION)) {
            setBackwardPanel(id);
        } else if (occurredAction.equals(Wizard.NEXT_ACTION)) {
            setForwardPanel(id);
        }
    }

    private void setStartingPanel(String startPanelId) {
        try {
            // Set the Current panel as the first.
            registerCurrentPanel(startPanelId);
            // The previouse panel is the same as the wellcome panel.
            previousPanelIdentifier = getCurrentPanelDescriptor().getIdentifier();
            // Tell the wellcome panel that is shown.
            getCurrentPanelDescriptor().getPanelController().displayingPanel();
            //Tell the wizard to show the current panel label.
            myWizard.setCurrentWizardLabel(0,0);
        } catch (WizardException ex) {
            JOptionPane.showMessageDialog(myWizard, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        } 
    }

    private void setBackwardPanel(String backPanelId) {
        try {
            //If the back panel ID is undefined then use the previouse panel ID.
            if (backPanelId.equals(WizardPanelDescriptor.UNKNOW_PANEL_ID)) {
                backPanelId = previousPanelIdentifier;
            }
            //Recover the current panel ordinal number.
            int currentPanelOrdinalNumber = getCurrentPanelDescriptor().getWizardPanelOrdinalNumber();
            //Register the current panel as the back panel.
            registerCurrentPanel(backPanelId);
            // Tell current panel that is shown.
            getCurrentPanelDescriptor().getPanelController().displayingPanel();
            //Recover the back panel id.
            int backPanelOrdinalNumber = getCurrentPanelDescriptor().getWizardPanelOrdinalNumber();
            //Tell the wizard to show the current panel label.
            myWizard.setCurrentWizardLabel(currentPanelOrdinalNumber, backPanelOrdinalNumber);
        }
        catch (WizardException ex) {
            JOptionPane.showMessageDialog(myWizard, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void setForwardPanel(String nextPanelId) {
        try {
            //Recover the current panel descriptor.
            WizardPanelDescriptor currentPanelDescriptor = getCurrentPanelDescriptor();
            //Recover the current panel ordinal number.
            int currentPanelOrdinalNumber = currentPanelDescriptor.getWizardPanelOrdinalNumber();
            //Check if the current panel can be closed.
            if (currentPanelDescriptor.getPanelController().aboutToHidePanel()) {
                //Recover the forkward object.
                Object fo = currentPanelDescriptor.getPanelController().getForwardObject();
                //Temporarily set the next panel by using the received identifier.
                registerCurrentPanel(nextPanelId);
                //Set the backward object to the next panel, as the forward object.
                getCurrentPanelDescriptor().getPanelController().setBackwardObject(fo);
                //Check if the next panel can be opened.
                if (getCurrentPanelDescriptor().getPanelController().aboutToDisplayPanel()) {
                    //Ok, now get user confirmation
                    if (getUserConfirmation(currentPanelDescriptor)) {
                        //Set the previous panel ID as the current but only if the current panel knows is backward panel
                        setPreviousPanelIfExists(currentPanelDescriptor);
                        //Display the next panel and return;
                        getCurrentPanelDescriptor().getPanelController().displayingPanel();
                        //Recover the next panel ordinal number
                        int nextPanelOrdinalNumber = getCurrentPanelDescriptor().getWizardPanelOrdinalNumber();
                        //Tell the wizard to update the showing panel label.
                        myWizard.setCurrentWizardLabel(currentPanelOrdinalNumber,nextPanelOrdinalNumber);
                        //Return so as to display the next panel.
                        return;
                    }
                }
                //The next panel cannot be opened or the user wants to review the form so rollback to the current panel.
                registerCurrentPanel(currentPanelDescriptor.getIdentifier());
            }
        }
        catch (WizardException ex) {
            JOptionPane.showMessageDialog(myWizard, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void setPreviousPanelIfExists(WizardPanelDescriptor currentPanelDescriptor){
        if(currentPanelDescriptor.getBackIdentifier() == null){
            return;
        }
        if((currentPanelDescriptor.getBackIdentifier().equals(WizardPanelDescriptor.UNKNOW_PANEL_ID))){
            return;
        }
        previousPanelIdentifier = currentPanelDescriptor.getIdentifier();
    }

    private boolean getUserConfirmation(WizardPanelDescriptor descriptor) {
        boolean confirm = true;
        if (descriptor.isUserConfirmationRequired()) {
            Object[] options = {"Yes, please", "No, thanks"};
            int resp = JOptionPane.showOptionDialog(myWizard,
                    "Do you want to proceed with these values? ",
                    "Create Capability Revocation",
                    JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    null,
                    options,
                    options[0]);
            confirm = (resp == JOptionPane.YES_OPTION ? true : false);
        }
        return confirm;
    }
}
